/*
 * PWM工具函数实现
 * 功能：实现Linux sysfs PWM接口的封装函数
 * 作者：test_code项目
 */

#include "pwm_utils.h"
#include <stdarg.h>
#include <sys/time.h>

// 全局调试开关
static int pwm_debug_enabled = 0;

// 内部辅助函数：写入文件
static int pwm_write_file(const char *path, const char *value) {
    FILE *file = fopen(path, "w");
    if (!file) {
        pwm_error_print("无法打开文件进行写入: %s - %s\n", path, strerror(errno));
        return PWM_ERROR_FILE_ACCESS;
    }
    
    if (fprintf(file, "%s", value) < 0) {
        fclose(file);
        pwm_error_print("写入文件失败: %s\n", path);
        return PWM_ERROR_WRITE_FAILED;
    }
    
    fclose(file);
    pwm_debug_print("写入文件成功: %s = %s\n", path, value);
    return PWM_SUCCESS;
}

// 内部辅助函数：读取文件
static int pwm_read_file(const char *path, char *buffer, size_t buffer_size) {
    FILE *file = fopen(path, "r");
    if (!file) {
        pwm_error_print("无法打开文件进行读取: %s - %s\n", path, strerror(errno));
        return PWM_ERROR_FILE_ACCESS;
    }
    
    if (!fgets(buffer, buffer_size, file)) {
        fclose(file);
        pwm_error_print("读取文件失败: %s\n", path);
        return PWM_ERROR_READ_FAILED;
    }
    
    fclose(file);
    
    // 移除换行符
    size_t len = strlen(buffer);
    if (len > 0 && buffer[len-1] == '\n') {
        buffer[len-1] = '\0';
    }
    
    pwm_debug_print("读取文件成功: %s = %s\n", path, buffer);
    return PWM_SUCCESS;
}

// 内部辅助函数：检查文件是否存在
static int pwm_file_exists(const char *path) {
    struct stat st;
    return (stat(path, &st) == 0);
}

// PWM导出
int pwm_export(int chip, int channel) {
    char path[PWM_MAX_PATH_LEN];
    char value[PWM_MAX_VALUE_LEN];
    
    // 检查是否已经导出
    if (pwm_is_exported(chip, channel)) {
        pwm_debug_print("PWM %d:%d 已经导出\n", chip, channel);
        return PWM_SUCCESS;
    }
    
    snprintf(path, sizeof(path), "%s/pwmchip%d/export", PWM_SYSFS_BASE_PATH, chip);
    snprintf(value, sizeof(value), "%d", channel);
    
    int result = pwm_write_file(path, value);
    if (result == PWM_SUCCESS) {
        // 等待sysfs创建完成
        usleep(100000); // 100ms
        pwm_debug_print("PWM %d:%d 导出成功\n", chip, channel);
    }
    
    return result;
}

// PWM取消导出
int pwm_unexport(int chip, int channel) {
    char path[PWM_MAX_PATH_LEN];
    char value[PWM_MAX_VALUE_LEN];
    
    // 先禁用PWM
    pwm_disable(chip, channel);
    
    snprintf(path, sizeof(path), "%s/pwmchip%d/unexport", PWM_SYSFS_BASE_PATH, chip);
    snprintf(value, sizeof(value), "%d", channel);
    
    int result = pwm_write_file(path, value);
    if (result == PWM_SUCCESS) {
        pwm_debug_print("PWM %d:%d 取消导出成功\n", chip, channel);
    }
    
    return result;
}

// 检查PWM是否已导出
int pwm_is_exported(int chip, int channel) {
    char path[PWM_MAX_PATH_LEN];
    snprintf(path, sizeof(path), "%s/pwmchip%d/pwm%d", PWM_SYSFS_BASE_PATH, chip, channel);
    return pwm_file_exists(path);
}

// 设置PWM周期
int pwm_set_period(int chip, int channel, unsigned long period_ns) {
    char path[PWM_MAX_PATH_LEN];
    char value[PWM_MAX_VALUE_LEN];
    
    if (!pwm_is_exported(chip, channel)) {
        pwm_error_print("PWM %d:%d 未导出\n", chip, channel);
        return PWM_ERROR_NOT_EXPORTED;
    }
    
    // 在设置周期前需要禁用PWM
    pwm_disable(chip, channel);
    
    snprintf(path, sizeof(path), "%s/pwmchip%d/pwm%d/period", PWM_SYSFS_BASE_PATH, chip, channel);
    snprintf(value, sizeof(value), "%lu", period_ns);
    
    return pwm_write_file(path, value);
}

// 设置PWM占空比
int pwm_set_duty_cycle(int chip, int channel, unsigned long duty_ns) {
    char path[PWM_MAX_PATH_LEN];
    char value[PWM_MAX_VALUE_LEN];
    
    if (!pwm_is_exported(chip, channel)) {
        pwm_error_print("PWM %d:%d 未导出\n", chip, channel);
        return PWM_ERROR_NOT_EXPORTED;
    }
    
    snprintf(path, sizeof(path), "%s/pwmchip%d/pwm%d/duty_cycle", PWM_SYSFS_BASE_PATH, chip, channel);
    snprintf(value, sizeof(value), "%lu", duty_ns);
    
    return pwm_write_file(path, value);
}

// 设置PWM极性
int pwm_set_polarity(int chip, int channel, pwm_polarity_t polarity) {
    char path[PWM_MAX_PATH_LEN];
    const char *value = (polarity == PWM_POLARITY_NORMAL) ? "normal" : "inversed";
    
    if (!pwm_is_exported(chip, channel)) {
        pwm_error_print("PWM %d:%d 未导出\n", chip, channel);
        return PWM_ERROR_NOT_EXPORTED;
    }
    
    // 设置极性前需要禁用PWM
    pwm_disable(chip, channel);
    
    snprintf(path, sizeof(path), "%s/pwmchip%d/pwm%d/polarity", PWM_SYSFS_BASE_PATH, chip, channel);
    
    return pwm_write_file(path, value);
}

// 启用PWM
int pwm_enable(int chip, int channel) {
    char path[PWM_MAX_PATH_LEN];
    
    if (!pwm_is_exported(chip, channel)) {
        pwm_error_print("PWM %d:%d 未导出\n", chip, channel);
        return PWM_ERROR_NOT_EXPORTED;
    }
    
    snprintf(path, sizeof(path), "%s/pwmchip%d/pwm%d/enable", PWM_SYSFS_BASE_PATH, chip, channel);
    
    return pwm_write_file(path, "1");
}

// 禁用PWM
int pwm_disable(int chip, int channel) {
    char path[PWM_MAX_PATH_LEN];
    
    if (!pwm_is_exported(chip, channel)) {
        // PWM未导出时认为已经禁用
        return PWM_SUCCESS;
    }
    
    snprintf(path, sizeof(path), "%s/pwmchip%d/pwm%d/enable", PWM_SYSFS_BASE_PATH, chip, channel);
    
    return pwm_write_file(path, "0");
}

// 获取PWM周期
int pwm_get_period(int chip, int channel, unsigned long *period_ns) {
    char path[PWM_MAX_PATH_LEN];
    char buffer[PWM_MAX_VALUE_LEN];
    
    if (!pwm_is_exported(chip, channel)) {
        return PWM_ERROR_NOT_EXPORTED;
    }
    
    snprintf(path, sizeof(path), "%s/pwmchip%d/pwm%d/period", PWM_SYSFS_BASE_PATH, chip, channel);
    
    int result = pwm_read_file(path, buffer, sizeof(buffer));
    if (result == PWM_SUCCESS) {
        *period_ns = strtoul(buffer, NULL, 10);
    }
    
    return result;
}

// 获取PWM占空比
int pwm_get_duty_cycle(int chip, int channel, unsigned long *duty_ns) {
    char path[PWM_MAX_PATH_LEN];
    char buffer[PWM_MAX_VALUE_LEN];
    
    if (!pwm_is_exported(chip, channel)) {
        return PWM_ERROR_NOT_EXPORTED;
    }
    
    snprintf(path, sizeof(path), "%s/pwmchip%d/pwm%d/duty_cycle", PWM_SYSFS_BASE_PATH, chip, channel);
    
    int result = pwm_read_file(path, buffer, sizeof(buffer));
    if (result == PWM_SUCCESS) {
        *duty_ns = strtoul(buffer, NULL, 10);
    }
    
    return result;
}

// 获取PWM极性
int pwm_get_polarity(int chip, int channel, pwm_polarity_t *polarity) {
    char path[PWM_MAX_PATH_LEN];
    char buffer[PWM_MAX_VALUE_LEN];
    
    if (!pwm_is_exported(chip, channel)) {
        return PWM_ERROR_NOT_EXPORTED;
    }
    
    snprintf(path, sizeof(path), "%s/pwmchip%d/pwm%d/polarity", PWM_SYSFS_BASE_PATH, chip, channel);
    
    int result = pwm_read_file(path, buffer, sizeof(buffer));
    if (result == PWM_SUCCESS) {
        *polarity = (strcmp(buffer, "normal") == 0) ? PWM_POLARITY_NORMAL : PWM_POLARITY_INVERSED;
    }
    
    return result;
}

// 获取PWM状态
int pwm_get_state(int chip, int channel, pwm_state_t *enabled) {
    char path[PWM_MAX_PATH_LEN];
    char buffer[PWM_MAX_VALUE_LEN];
    
    if (!pwm_is_exported(chip, channel)) {
        *enabled = PWM_STATE_DISABLED;
        return PWM_ERROR_NOT_EXPORTED;
    }
    
    snprintf(path, sizeof(path), "%s/pwmchip%d/pwm%d/enable", PWM_SYSFS_BASE_PATH, chip, channel);
    
    int result = pwm_read_file(path, buffer, sizeof(buffer));
    if (result == PWM_SUCCESS) {
        *enabled = (atoi(buffer) == 1) ? PWM_STATE_ENABLED : PWM_STATE_DISABLED;
    }
    
    return result;
}

// 获取PWM完整信息
int pwm_get_info(int chip, int channel, pwm_info_t *info) {
    if (!info) {
        return PWM_ERROR_INVALID_PARAM;
    }
    
    info->chip = chip;
    info->channel = channel;
    
    if (!pwm_is_exported(chip, channel)) {
        return PWM_ERROR_NOT_EXPORTED;
    }
    
    int result = PWM_SUCCESS;
    
    if (pwm_get_period(chip, channel, &info->period) != PWM_SUCCESS) {
        result = PWM_ERROR_READ_FAILED;
    }
    
    if (pwm_get_duty_cycle(chip, channel, &info->duty_cycle) != PWM_SUCCESS) {
        result = PWM_ERROR_READ_FAILED;
    }
    
    if (pwm_get_polarity(chip, channel, &info->polarity) != PWM_SUCCESS) {
        result = PWM_ERROR_READ_FAILED;
    }
    
    if (pwm_get_state(chip, channel, &info->enabled) != PWM_SUCCESS) {
        result = PWM_ERROR_READ_FAILED;
    }
    
    return result;
}

// 打印PWM信息
void pwm_print_info(const pwm_info_t *info) {
    if (!info) return;
    
    printf("PWM信息:\n");
    printf("  芯片: %d\n", info->chip);
    printf("  通道: %d\n", info->channel);
    printf("  周期: %lu ns (%.2f Hz)\n", info->period, pwm_period_to_frequency(info->period));
    printf("  占空比: %lu ns (%.2f%%)\n", info->duty_cycle, 
           pwm_duty_cycle_to_percent(info->period, info->duty_cycle));
    printf("  极性: %s\n", (info->polarity == PWM_POLARITY_NORMAL) ? "正常" : "反向");
    printf("  状态: %s\n", (info->enabled == PWM_STATE_ENABLED) ? "启用" : "禁用");
}

// 列出PWM芯片
int pwm_list_chips(int *chips, int max_chips) {
    DIR *dir = opendir(PWM_SYSFS_BASE_PATH);
    if (!dir) {
        pwm_error_print("无法打开PWM sysfs目录: %s\n", PWM_SYSFS_BASE_PATH);
        return 0;
    }
    
    struct dirent *entry;
    int count = 0;
    
    while ((entry = readdir(dir)) != NULL && count < max_chips) {
        if (strncmp(entry->d_name, "pwmchip", 7) == 0) {
            int chip_num = atoi(entry->d_name + 7);
            chips[count++] = chip_num;
        }
    }
    
    closedir(dir);
    return count;
}

// 获取芯片PWM通道数
int pwm_get_chip_npwm(int chip) {
    char path[PWM_MAX_PATH_LEN];
    char buffer[PWM_MAX_VALUE_LEN];
    
    snprintf(path, sizeof(path), "%s/pwmchip%d/npwm", PWM_SYSFS_BASE_PATH, chip);
    
    if (pwm_read_file(path, buffer, sizeof(buffer)) == PWM_SUCCESS) {
        return atoi(buffer);
    }
    
    return -1;
}

// 显示系统PWM信息
void pwm_show_system_info(void) {
    printf("=== 系统PWM设备信息 ===\n");
    
    int chips[16];
    int chip_count = pwm_list_chips(chips, 16);
    
    if (chip_count == 0) {
        printf("未找到PWM设备\n");
        return;
    }
    
    printf("发现 %d 个PWM芯片:\n", chip_count);
    
    for (int i = 0; i < chip_count; i++) {
        int chip = chips[i];
        int npwm = pwm_get_chip_npwm(chip);
        
        printf("\nPWM芯片 %d:\n", chip);
        printf("  通道数: %d\n", npwm);
        
        if (npwm > 0) {
            printf("  通道状态:\n");
            for (int ch = 0; ch < npwm; ch++) {
                if (pwm_is_exported(chip, ch)) {
                    pwm_info_t info;
                    if (pwm_get_info(chip, ch, &info) == PWM_SUCCESS) {
                        printf("    通道 %d: 已导出, %s, %.2f Hz, %.1f%%\n", 
                               ch,
                               (info.enabled == PWM_STATE_ENABLED) ? "启用" : "禁用",
                               pwm_period_to_frequency(info.period),
                               pwm_duty_cycle_to_percent(info.period, info.duty_cycle));
                    } else {
                        printf("    通道 %d: 已导出 (无法读取详细信息)\n", ch);
                    }
                } else {
                    printf("    通道 %d: 未导出\n", ch);
                }
            }
        }
    }
}

// 高级功能：设置频率和占空比百分比
int pwm_set_frequency_duty(int chip, int channel, double freq_hz, double duty_percent) {
    if (freq_hz <= 0 || duty_percent < 0 || duty_percent > 100) {
        return PWM_ERROR_INVALID_PARAM;
    }
    
    unsigned long period = pwm_frequency_to_period(freq_hz);
    unsigned long duty = pwm_percent_to_duty_cycle(period, duty_percent);
    
    int result = pwm_set_period(chip, channel, period);
    if (result != PWM_SUCCESS) {
        return result;
    }
    
    return pwm_set_duty_cycle(chip, channel, duty);
}

// 工具函数：错误代码转字符串
const char* pwm_error_string(int error_code) {
    switch (error_code) {
        case PWM_SUCCESS:           return "成功";
        case PWM_ERROR_INVALID_PARAM: return "无效参数";
        case PWM_ERROR_FILE_ACCESS: return "文件访问错误";
        case PWM_ERROR_WRITE_FAILED: return "写入失败";
        case PWM_ERROR_READ_FAILED: return "读取失败";
        case PWM_ERROR_NOT_EXPORTED: return "PWM未导出";
        default:                    return "未知错误";
    }
}

// 参数验证
int pwm_validate_parameters(unsigned long period_ns, unsigned long duty_ns) {
    if (period_ns == 0) {
        return PWM_ERROR_INVALID_PARAM;
    }
    
    if (duty_ns > period_ns) {
        return PWM_ERROR_INVALID_PARAM;
    }
    
    return PWM_SUCCESS;
}

// 延时函数
void pwm_delay_ms(int milliseconds) {
    usleep(milliseconds * 1000);
}

void pwm_delay_us(int microseconds) {
    usleep(microseconds);
}

// 计算辅助函数
double pwm_duty_cycle_to_percent(unsigned long period_ns, unsigned long duty_ns) {
    if (period_ns == 0) return 0.0;
    return (double)duty_ns / period_ns * 100.0;
}

unsigned long pwm_percent_to_duty_cycle(unsigned long period_ns, double percent) {
    return (unsigned long)(period_ns * percent / 100.0);
}

double pwm_period_to_frequency(unsigned long period_ns) {
    if (period_ns == 0) return 0.0;
    return 1000000000.0 / period_ns;
}

unsigned long pwm_frequency_to_period(double freq_hz) {
    if (freq_hz <= 0) return 0;
    return (unsigned long)(1000000000.0 / freq_hz);
}

// 调试和日志函数
void pwm_debug_print(const char *format, ...) {
    if (!pwm_debug_enabled) return;
    
    va_list args;
    va_start(args, format);
    printf("[PWM DEBUG] ");
    vprintf(format, args);
    va_end(args);
}

void pwm_error_print(const char *format, ...) {
    va_list args;
    va_start(args, format);
    fprintf(stderr, "[PWM ERROR] ");
    vfprintf(stderr, format, args);
    va_end(args);
}